﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using TechTalk.SpecFlow;
using System.Drawing.Imaging;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using System.IO;
using System.Threading;

namespace CERT.AcceptanceTests
{
    //http://blogs.lessthandot.com/index.php/EnterpriseDev/application-lifecycle-management/using-specflow-to
    public class TestFixtureBase //: PageLibrary.Base.PageBase
    {
        protected RemoteWebDriver CurrentDriver { get; set; }
       
        [SetUp]
        public void Test_Setup()
        {
            FirefoxBinary fb;
           
            if (!String.IsNullOrWhiteSpace(Settings.CurrentSettings.FirefoxBinaryPath))
            {
                     fb = new FirefoxBinary(Settings.CurrentSettings.FirefoxBinaryPath);
                 
 
            }
            else
            {
                fb = new FirefoxBinary();
            }
            
            CurrentDriver = new FirefoxDriver(fb, new FirefoxProfile());
        }



        [TearDown]
        public void Test_Teardown()
        {
            try
            {
                if (TestContext.CurrentContext.Result.Status == TestStatus.Failed
                        && CurrentDriver is ITakesScreenshot)
                {
                    ((ITakesScreenshot)CurrentDriver).GetScreenshot().SaveAsFile(TestContext.CurrentContext.Test.FullName + ".jpg", ImageFormat.Jpeg);
                }
            }
            catch { }	// null ref exception occurs from accessing TestContext.CurrentContext.Result.Status property

            try
            {
                CurrentDriver.Quit();
            }
            catch { }
        }


        public void ClearAndType(IWebElement element, string value)
        {
            element.Clear();
            element.SendKeys(value);
        }

        public void WaitUpTo(int milliseconds, Func<bool> Condition, string description)
        {
            int timeElapsed = 0;
            while (!Condition() && timeElapsed < milliseconds)
            {
                Thread.Sleep(100);
                timeElapsed += 100;
            }

            if (timeElapsed >= milliseconds || !Condition())
            {
                throw new AssertionException("Timed out while waiting for: " + description);
            }
        }

        public void WaitUpTo(int milliseconds, string description)
        {
            int timeElapsed = 0;
            while ( timeElapsed < milliseconds)
            {
                Thread.Sleep(100);
                timeElapsed += 100;
            }

            
        }

        public string BaseURL { get; set; }
        public virtual string DefaultTitle { get { return ""; } }

        protected TPage GetInstance<TPage>(RemoteWebDriver driver = null, string expectedTitle = "") where TPage : TestFixtureBase, new()
        {
            return GetInstance<TPage>(driver ?? CurrentDriver, BaseURL, expectedTitle);
        }

        static TPage GetInstance<TPage>(RemoteWebDriver driver, string baseUrl, string expectedTitle = "") where TPage : TestFixtureBase, new()
        {
            TPage pageInstance = new TPage()
            {
                CurrentDriver = driver,
                BaseURL = baseUrl
            };
            PageFactory.InitElements(driver, pageInstance);

            if (string.IsNullOrWhiteSpace(expectedTitle)) expectedTitle = pageInstance.DefaultTitle;

            //wait up to 5s for an actual page title since Selenium no longer waits for page to load after 2.21
            new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(5))
                                            .Until<OpenQA.Selenium.IWebElement>((d) =>
                                            {
                                                return d.FindElement(ByChained.TagName("body"));
                                            });

            //AssertIsEqual(expectedTitle, driver.Title, "Page Title");

            return pageInstance;
        }

    }
}
